<?php
class im {
	
	public static function getMillisecond() {
		list($s1, $s2) = explode(' ', microtime());
		return (float)sprintf('%.0f', (floatval($s1) + floatval($s2)) * 1000);
	}
	
	public static function getsigns($str , $slen , $no)
	{
		$Mod_Prime_List_1=array(
				15824477,   7761153,   7145686,    580925,  14499208,   4036269,   9875725,  11605750,
				1507777,    115335,  12748561,   8855010,   1960695,  15399149,  16317578,  16554616,
				10127548,   8963642,  12993288,   4396326,   1387123,   2782309,   7628746,   6803892,
				13744855,  12248289,  15002970,  15558948,   6894525,   3392505,  12844131,  16543731,
				7340988,    246640,  12808243,   7356403,   4192880,  16413743,   7618458,   4170164,
				10598447,  12073393,   3783992,  12401609,   3921293,  13996267,   9500965,  16330384,
				3055753,  10521614,   9181344,   1616204,  11095448,   5088057,  10698269,   4073427,
				2610974,  14098583,   2139463,  10832160,   4795125,   2816473,  16374730,  14408329,
				14325643,   9935226,  10060807,   8655145,   1126852,   3261729,  12919873,   2379285,
				5117796,   1534254,   6893447,   3116537,   9305119,  16525405,   2649532,   7192232,
				12496701,  11487646,   4827551,  11117529,  10740793,  14959571,   4448804,  14821491,
				2654722,   8520872,    307362,  11575876,  10637232,   5225154,  12240703,  13060954,
				4941623,   6765563,   3932631,    121596,  14351377,  16523130,   2067132,   9092623,
				12458026,   1586846,   3579800,  10460054,  10199183,  10525003,  10048928,   5614121,
				11153061,   3059786,  11554062,   5052848,   1684765,  11869865,   2012421,  11863806,
				461317,    656759,    358314,   7842389,  11164903,   6091338,  15880220,   5254162,
				2889552,   1528556,   5434759,  15567986,   9208253,   8504908,  12997777,   5545510,
				10365844,   2858622,  10387675,   8447358,  15042176,   8818485,   9387494,   4059007,
				15696653,   8592607,   1894323,  15185116,  11856727,  15426292,   6488987,    237971,
				10588979,   9649585,   4045507,  12240653,  13048154,   1664823,   6764713,   3715031,
				11524792,  14336927,  12823930,  11372275,   8846973,  16680422,   8779486,  16180949,
				15131990,  15033670,   6640949,   5585845,   3914405,  12232939,  11073370,  16213288,
				6633575,   3698101,   7190712,  12107581,  12536120,   4801711,   4502489,  11787652,
				14520291,   9433517,  15840895,  11964161,   9374998,    860031,   2064349,   8380175,
				14620527,   1539535,   8245383,  13668173,   9394896,   5953919,  14255354,   8718441,
				553429,   7460232,  13995905,   9408293,   9383551,   3049599,   8946190,   8525576,
				1511586,   1090439,  10717200,   8919763,   1760264,  14420410,    641180,  13147289,
				10266184,  10900060,   5400326,   6753138,    751831,   7919547,  14140152,  12781127,
				414707,   5501798,  15952771,   7050019,   9644571,   2761923,   2409930,  12962916,
				13398293,   7414412,   2265985,   9667394,   8604611,   4967347,  13350907,  12060795,
				558904,   8861832,   3707127,   9501368,  16433552,  12689562,  10528465,  10935200,
				14396166,  11211915,   1349211,   9854036,   6053366,   6159388,  16523821,   2244028
		);
		
		$Mod_Prime_List_2=array(
				4046946,  12610013,   6944192,  16108937,  13478037,  11054957,  11502248,   8568463,
				12492738,  10476158,  14324351,   9607962,  10169554,   2942459,  15073452,     51622,
				13215232,  10885609,   1703526,  16673081,   6904254,   5884809,  13341817,   9737003,
				9649684,   4073203,   2554622,  16450278,    198235,    416611,   5989318,   6541755,
				13748163,  13098481,  14551719,    705438,  12820298,  10445603,   6502271,   3640259,
				9161239,  13248747,   2688266,    331593,   1001893,   4826863,  10942569,  16285286,
				8291832,   8783934,    544582,   5195528,   4657711,   1194023,   3680594,   2709816,
				5848393,   4019321,   5538013,   8447956,  15197312,  14982599,  10347620,  14972989,
				7887460,   5927800,   7570330,   8628435,  11068387,  14940328,  16303427,  12935928,
				6492517,   1143235,   7456049,  12926865,   4172389,  11169055,   7156970,   3471373,
				16257972,   1299448,  13892211,  16420403,   9327418,   5459022,   5003443,   5815500,
				12375896,  14118972,   7362487,   5752176,  12942135,   8081509,   5272795,   7660880,
				15032052,   6230405,   1151295,   9519409,   4277169,   4438369,  12151203,   6929113,
				12248713,  15114490,  10557350,   1555137,  12239863,  12848890,    987972,   1263087,
				4583795,  15825893,   8127505,    270588,   2161796,  16549920,   8929404,   4230536,
				9277504,   9458221,   5390224,   4168338,  10131999,  10105562,   3337690,  15589490,
				14717069,   9480672,  11137680,  15902153,  10872882,  15222597,   4678376,   6484263,
				15807394,   3391761,  12654483,   1551329,  11265015,  14945547,    862308,   2647469,
				6664744,  11678981,   3480562,   1833173,  16308347,  14195448,  10163160,   1305595,
				15465843,  16617803,   9530269,   7057329,  11517643,  12509583,  14788478,  10984193,
				10163847,   1481467,  10157526,  16640474,  15334045,  16431881,  12265786,   2707995,
				5382217,   2118546,   5477920,   9841331,   2803286,  12999530,   5997446,   8622523,
				9554915,  13366705,  16108331,  13322901,   4894507,  11482250,   3448975,  10524084,
				9816224,  13153077,  11751112,   5168915,  14621966,   1911487,   2802365,  12763754,
				12747522,   8592130,   1774307,   1238651,  15105362,   8220582,   7321117,  11938639,
				2844278,   6716299,   8099878,   9975259,   3534488,  15638229,  10417070,  15975006,
				12746067,   8219650,   7082525,   1190636,   2813522,  15619946,   5736622,   8960311,
				12142728,   4759513,  10478152,  14834815,   6069282,  10235356,   3010588,  15737293,
				2223088,  15463489,  16015179,   6253172,   6979647,   8408234,   5028480,  12224972,
				9036794,  14945193,    771684,  13002091,   6653062,   8688389,   9639428,   1447667,
				1504726,  16111830,  14218645,  16101592,  11597717,  16231344,  11259863,  13626635,
				15541679,   2477453,  13472197,   9559917,  14647217,   8375743,  13487967,  13597037
		);
		
		$i=0;
		$itemp=0;
	
		while ($i < $slen){
			if($no == 1)
				$itemp= (ord($str[$i]) * $Mod_Prime_List_1[0xFF & ($i++)]+$itemp);
			else 
				$itemp= (ord($str[$i]) * $Mod_Prime_List_2[0xFF & ($i++)]+$itemp);
		}
		return (int)$itemp;
	}
	
	
	public static function createMsgNo($custid, $tcustid , $chatid){
		$str = $custid . ":" . $tcustid . ":" . $chatid . ":" . self::getMillisecond();
		$sign1 = self::getsigns($str , strlen($str) , 1);
		$sign2 = self::getsigns($str , strlen($str) , 2);
		
		//4294967296 = 2^32
		//18446744073709551616 = 2^64
		$msg_no = bcmod(bcadd(bcmul($sign2 , "4294967296") , $sign1) , "18446744073709551616");
		/* if($msg_no[0] == "-"){
			$msg_no = bcadd("18446744073709551616" , $msg_no);
		} */
		
		return $msg_no;
	}
	

	/**
	 * 添加好友
	 * type 1:分配系统server 2:发消息 3:同步修改数据
	 * cmd 0:初始化 1:添加 2:修改 3:删除 
	 * optype 1:好友相关 2:群相关 3:黑名单相关 4:群成员相关 5:系统账号相关
	 * @param type $custid
	 * @param type $tcustid
	 */
	public static function addFriend($custid, $tcustid , $client=0) {
		$data = array(array('id' => (int)$custid, 'list' => array((int)$tcustid)), array('id' => (int)$tcustid, 'list' => array((int)$custid)));
		$url = C('IM_API_URL');
		$params['type'] = 3; //同步修改数据
		$params['client'] = (int)$client;
		$params['optype'] = 1; //好友相关
		$params['cmd'] = 1; //添加
		$params['content'] = urlencode(json_encode($data));
		$result = self::httpUrl($url, $params, 'GET');
		return $result;
	}

	/**
	 * 删除好友
	 * type 1:分配系统server 2:发消息 3:同步修改数据
	 * cmd 0:初始化 1:添加 2:修改 3:删除 
	 * optype 1:好友相关 2:群相关 3:黑名单相关 4:群成员相关 5:系统账号相关
	 * @param type $custid
	 * @param type $tcustid
	 */
	public static function delFriend($custid, $tcustid , $client=0) {
		$data = array(array('id' => (int)$custid, 'list' => array((int)$tcustid)), array('id' => (int)$tcustid, 'list' => array((int)$custid)));
		$url = C('IM_API_URL');
		$params['type'] = 3; //同步修改数据
		$params['client'] = (int)$client;
		$params['optype'] = 1; //好友相关
		$params['cmd'] = 3; //删除
		$params['content'] = urlencode(json_encode($data));
		$result = self::httpUrl($url, $params, 'GET');
		return $result;
	}

	/**
	 * 添加群聊成员
	 * type 1:分配系统server 2:发消息 3:同步修改数据
	 * cmd 0:初始化 1:添加 2:修改 3:删除 
	 * optype 1:好友相关 2:群相关 3:黑名单相关 4:群成员相关 5:系统账号相关
	 * @param type $chatid
	 * @param type $custs
	 */
	public static function addGroupCusts($chatid, $custs , $client=0) {
		foreach ($custs as $index => $cust) {
			$custs[$index] = (int)$cust;
		}
		$data = array(array('id' => (int)$chatid, 'list' => $custs));
		$url = C('IM_API_URL');
		$params['type'] = 3; //同步修改数据
		$params['client'] = (int)$client;
		$params['optype'] = 4; //群成员相关
		$params['cmd'] = 1; //添加
		$params['content'] = urlencode(json_encode($data));
		$result = self::httpUrl($url, $params, 'GET');
		return $result;
	}

	/**
	 * 删除群聊成员
	 * type 1:分配系统server 2:发消息 3:同步修改数据
	 * cmd 0:初始化 1:添加 2:修改 3:删除 
	 * optype 1:好友相关 2:群相关 3:黑名单相关 4:群成员相关 5:系统账号相关
	 * @param type $chatid
	 * @param type $custs
	 */
	public static function delGroupCusts($chatid, $custs , $client=0) {
		foreach ($custs as $index => $cust) {
			$custs[$index] = (int)$cust;
		}
		$data = array(array('id' => (int)$chatid, 'list' => $custs));
		$url = C('IM_API_URL');
		$params['type'] = 3; //同步修改数据
		$params['client'] = (int)$client;
		$params['optype'] = 4; //群成员相关
		$params['cmd'] = 3; //删除
		$params['content'] = urlencode(json_encode($data));
		$result = self::httpUrl($url, $params, 'GET');
		return $result;
	}

	/**
	 * 建群
	 * type 1:分配系统server 2:发消息 3:同步修改数据
	 * cmd 0:初始化 1:添加 2:修改 3:删除 
	 * optype 1:好友相关 2:群相关 3:黑名单相关 4:群成员相关 5:系统账号相关
	 * @param type $chatid
	 * @param type $custs
	 */
	public static function addGroup($chatid, $custs , $client=0) {
		foreach ($custs as $index => $cust) {
			$custs[$index] = (int)$cust;
		}
		$data = array(array('id' => (int)$chatid, 'list' => $custs));
		$url = C('IM_API_URL');
		$params['type'] = 3; //同步修改数据
		$params['client'] = (int)$client;
		$params['optype'] = 2; //群相关
		$params['cmd'] = 1; //添加
		$params['content'] = urlencode(json_encode($data));
		$result = self::httpUrl($url, $params, 'GET');
		return $result;
	}

	/**
	 * 解散群
	 * type 1:分配系统server 2:发消息 3:同步修改数据
	 * cmd 0:初始化 1:添加 2:修改 3:删除 
	 * optype 1:好友相关 2:群相关 3:黑名单相关 4:群成员相关 5:系统账号相关
	 * @param type $chatid
	 */
	public static function delGroup($chatid , $client=0) {
		$data = array(array('id' => (int)$chatid, 'list' => array()));
		$url = C('IM_API_URL');
		$params['type'] = 3; //同步修改数据
		$params['client'] = (int)$client;
		$params['optype'] = 2; //群相关
		$params['cmd'] = 3; //删除
		$params['content'] = urlencode(json_encode($data));
		$result = self::httpUrl($url, $params, 'GET');
		return $result;
	}

	/**
	 * 添加黑名单成员
	 * type 1:分配系统server 2:发消息 3:同步修改数据
	 * cmd 0:初始化 1:添加 2:修改 3:删除 
	 * optype 1:好友相关 2:群相关 3:黑名单相关 4:群成员相关 5:系统账号相关
	 * @param type $custid
	 * @param type $custs
	 */
	public static function addBlacklist($custid, $custs , $client=0) {
		foreach ($custs as $index => $cust) {
			$custs[$index] = (int)$cust;
		}
		$data = array(array('id' => (int)$custid, 'list' => $custs));
		$url = C('IM_API_URL');
		$params['type'] = 3; //同步修改数据
		$params['client'] = (int)$client;
		$params['optype'] = 3; //黑名单相关
		$params['cmd'] = 1; //添加
		$params['content'] = urlencode(json_encode($data));
		$result = self::httpUrl($url, $params, 'GET');
		return $result;
	}

	/**
	 * 删除黑名单成员
	 * type 1:分配系统server 2:发消息 3:同步修改数据
	 * cmd 0:初始化 1:添加 2:修改 3:删除 
	 * optype 1:好友相关 2:群相关 3:黑名单相关 4:群成员相关 5:系统账号相关
	 * @param type $custid
	 * @param type $custs
	 */
	public static function delBlacklist($custid, $custs , $client=0) {
		foreach ($custs as $index => $cust) {
			$custs[$index] = (int)$cust;
		}
		$data = array(array('id' => (int)$custid, 'list' => $custs));
		$url = C('IM_API_URL');
		$params['type'] = 3; //同步修改数据
		$params['client'] = (int)$client;
		$params['optype'] = 3; //黑名单相关
		$params['cmd'] = 3; //删除
		$params['content'] = urlencode(json_encode($data));
		$result = self::httpUrl($url, $params, 'GET');
		return $result;
	}
	
	/**
	 * 增加系统账户
	 * type 1:分配系统server 2:发消息 3:同步修改数据
	 * cmd 0:初始化 1:添加 2:修改 3:删除 
	 * optype 1:好友相关 2:群相关 3:黑名单相关 4:群成员相关 5:系统账号相关
	 * @param type $custid
	 * @param type $custs
	 */
	public static function addSysAccount($custid, $custs , $client=0) {
		foreach ($custs as $index => $cust) {
			$custs[$index] = (int)$cust;
		}
		$data = array(array('id' => (int)$custid, 'list' => $custs));
		$url = C('IM_API_URL');
		$params['type'] = 3; //同步修改数据
		$params['client'] = (int)$client;
		$params['optype'] = 5; //系统账户相关
		$params['cmd'] = 1; //添加
		$params['content'] = urlencode(json_encode($data));
		$result = self::httpUrl($url, $params, 'GET');
		return $result;
	}
	
	/**
	 * 删除系统账户
	 * type 1:分配系统server 2:发消息 3:同步修改数据
	 * cmd 0:初始化 1:添加 2:修改 3:删除 
	 * optype 1:好友相关 2:群相关 3:黑名单相关 4:群成员相关 5:系统账号相关
	 * @param type $custid
	 * @param type $custs
	 */
	public static function delSysAccount($custid, $custs , $client=0) {
		foreach ($custs as $index => $cust) {
			$custs[$index] = (int)$cust;
		}
		$data = array(array('id' => (int)$custid, 'list' => $custs));
		$url = C('IM_API_URL');
		$params['type'] = 3; //同步修改数据
		$params['client'] = (int)$client;
		$params['optype'] = 5; //系统账户相关
		$params['cmd'] = 3; //删除
		$params['content'] = urlencode(json_encode($data));
		$result = self::httpUrl($url, $params, 'GET');
		return $result;
	}

	/**
	 * 发送消息
	 * type 1:分配系统server 2:发消息 3:同步修改数据
	 * @param $systype 0、所有在线人，1、好友friend（custs里面的friends）、2、聊天群（chatids里面的群组）3、指定人、4、kick人
		如果是0，是所有在线人员推送消息，不存未读消息
		如果是1，只发custs里面的人的好友
		如果是2，只发custs里面的群组，不存未读消息
		如果是3，只发custs里面的人
		如果是4，只发custs里面的人

	 * @param $custs 接收人id
	 * @param $chatids 接收群id
	 * @param $msg 消息内容
	 * @return $return
	 */
	public static function sendMsg($systype, $custs, $chatids, $msg , $client=0) {
		$msg_no = self::createMsgNo("0", implode("," , $custs) , implode("," , $chatids));
		foreach ($custs as $index => $cust) {
			$custs[$index] = (int)$cust;
		}
		foreach ($chatids as $index => $chatid) {
			$chatids[$index] = (int)$chatid;
		}
		
		//$data = array("sys_type" => $systype, 'cust_ids' => $custs, 'chat_ids' => $chatids, 'sys_content' => json_encode($msg));
		$url = C('IM_API_URL');
		$params['type'] = 2;  //发消息
		$params['client'] = (int)$client;
		$params['msg_no'] = $msg_no;  //消息编号
		$params['sys_type'] = $systype; //0、所有在线人，1、好友friend（custs里面的friends）、2、聊天群（chatids里面的群组）3、指定人、4、kick人
		$params['cust_ids'] = urlencode(json_encode($custs));  //接收人ids
		$params['chat_ids'] = urlencode(json_encode($chatids)); //接收群ids
		$params['content'] = urlencode(json_encode($msg)); //消息内容
		$result = self::httpUrl($url, $params, 'GET');
		return $result;
	}
	
	
	/**
	 * 获取talk的ip和端口
	 * custid 用户ID
	 * logintype 1:app登录 2:web登录
	 * auth 认证token
	 * ip 用户的ip
	 * @param int custid
	 * @param int logintype
	 * @param string auth
	 * @param string ip
	 */
	public static function getTalkServer($custid,$logintype,$auth,$ip) {
		$url = C('IM_API_URL');
		$params['type'] = 1; //获取talk server的ip和端口
		$params['cust_id'] = $custid; 
		$params['login_type'] = $logintype; 
		$params['auth'] = $auth; 
		$params['ip'] = $ip; 
		$result = self::httpUrl($url, $params, 'GET');
		return $result;
	}
	

	/**
	 * 请求URL
	 * @param type $url
	 * @param type $params
	 * @param type $type
	 * @return type
	 */
	private static function httpUrl($url, $params, $type) {
		$result = \tools::http_request($url, $params, $type);
		$return_data = json_decode($result, true);
		/* if ($return_data['res'] != 'OK') {
			$body .= "IM Server:\n";
			$body .= 'URL:' . $url . "\n";
			$body .= 'TYPE:' . $type . "\n";
			$body .= 'DATA:' . print_r($params, true) . "\n";
			$body .= urldecode($params['content']) . "\n";
			$body .= 'RETURN:' . print_r($result, true) . "\n";
			echo nl2br($body);
			system("echo {$body} >> /tmp/im.log");
		} */
		
		//if ($return_data['res'] != 'OK') {
		//system("echo ". date("Y-m-d H:i:s") . "   " .json_encode($params)." >> /tmp/im.log");
		//}
		//system("echo ".json_encode($params)." >> /tmp/im.log");
		return $return_data['res'];
	}

}
